import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error


class Simple_mlp_point_data:
	def __init__(self, point_file, batch_size, epochs, look_back):  
		self.look_back = look_back
		self.batch_size = batch_size
		self.epochs = epochs
		self.point_file = point_file
		self.compile_model()

	def compile_model(self):
		self.model = Sequential()
		# , input_shape=(40, 2)))
		self.model.add(Dense(128, activation='relu'))
		self.model.add(Dropout(0.15))
		self.model.add(Dense(64, activation='relu'))
		# self.model.add(Dropout(0.15))
		# self.model.add(Dense(8, activation='relu'))#, input_shape=(40, 2)))

		self.model.add(Flatten())
		self.model.add(Dense(1))
		self.model.compile(loss='mean_squared_error', optimizer='adam')

	def train(self):
		# convert an array of values into a dataset matrix

		def create_dataset(dataset, look_back=1):
			dataX, dataY = [], []
			for i in range(len(dataset)-look_back-1):
				a = dataset[i:(i+look_back), 0]
				dataX.append(a)
				dataY.append(dataset[i + look_back, 0])
			return numpy.array(dataX), numpy.array(dataY)

		# fix random seed for reproducibility
		numpy.random.seed(7)
		# load the dataset
		dataframe = read_csv(self.point_file, usecols=[
							 1], engine='python', skipfooter=3)
		dataset = dataframe.values
		dataset = dataset.astype('float32')
		# normalize the dataset
		scaler = MinMaxScaler(feature_range=(0, 1))
		dataset = scaler.fit_transform(dataset)
		# split into train and test sets
		train_size = int(len(dataset) * 0.67)
		test_size = len(dataset) - train_size
		train, test = dataset[0:train_size, :], dataset[train_size:len(dataset), :]
		# reshape into X=t and Y=t+1
		trainX, trainY = create_dataset(train, self.look_back)
		testX, testY = create_dataset(test, self.look_back)
		# reshape input to be [samples, time steps, features]
		trainX = numpy.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
		testX = numpy.reshape(testX, (testX.shape[0], 1, testX.shape[1]))
		# create and fit the LSTM network
		self.model.fit(trainX, trainY, epochs=self.epochs,
					   batch_size=self.batch_size, verbose=0)

		# make predictions
		trainPredict = self.model.predict(trainX)
		testPredict = self.model.predict(testX)
		# invert predictions
		trainPredict = scaler.inverse_transform(trainPredict)
		trainY = scaler.inverse_transform([trainY])
		testPredict = scaler.inverse_transform(testPredict)
		testY = scaler.inverse_transform([testY])
		# calculate root mean squared error
		trainScore = math.sqrt(mean_squared_error(trainY[0], trainPredict[:, 0]))
		print('Train Score: %.2f RMSE' % (trainScore))
		testScore = math.sqrt(mean_squared_error(testY[0], testPredict[:, 0]))
		print('Test Score: %.2f RMSE' % (testScore))
		# shift train predictions for plotting
		# trainPredictPlot = numpy.empty_like(dataset)
		# trainPredictPlot[:, :] = numpy.nan
		# trainPredictPlot[self.look_back:len(
		# 	trainPredict)+self.look_back, :] = trainPredict
		# # shift test predictions for plotting
		# testPredictPlot = numpy.empty_like(dataset)
		# testPredictPlot[:, :] = numpy.nan
		# testPredictPlot[len(trainPredict)+(self.look_back*2) +
		# 					1:len(dataset)-1, :] = testPredict
		# plot baseline and predictions
		# plt.plot(scaler.inverse_transform(dataset))
		# plt.plot(trainPredictPlot)
		# plt.plot(testPredictPlot)
		# plt.show()

	def run(self):
				
		self.train()